package com.googlecode.dgwt.client.dijit.view.store;

import java.util.List;

import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.Event;
import com.googlecode.dgwt.client.dijit.Dijit;
import com.googlecode.dgwt.client.dijit.view.render.base.CellRender;
import com.googlecode.dgwt.client.dojo.Dojo;
import com.googlecode.dgwt.client.dojo.data.base.ModeledStore;
import com.googlecode.dgwt.client.dojo.data.base.Store;
import com.googlecode.dgwt.client.dojo.data.listener.StoreListener;
import com.googlecode.dgwt.client.dojo.data.model.StoreColumn;
import com.googlecode.dgwt.client.dojo.exception.AttachException;

/**
 * Base class for views that works with a {@link ModeledStore}. <br/>
 * Provides general routines to render rows, to render cells and to fire events.
 * 
 * @author wellsantos@wellsantos.com
 * @since 0.01
 */
public abstract class CellViewBase extends RowViewBase implements StoreListener<Object>, CellView {

    // TODO : fazer sistema de focus para células quando rowSelect=false
    private boolean rowSelect = true;
    
    
    public CellViewBase() {
        super();
    }

    protected CellViewBase(boolean ready) {
        super(ready);
    }

    @Override
    protected abstract CellRender createRender();

    @Override
    protected CellRender getRender() {
        return (CellRender) super.getRender();
    }

    @Override
    public ModeledStore<Object> getStore(){
        return (ModeledStore<Object>) super.getStore();
    }

    public boolean isRowSelect() {
        return rowSelect;
    }

    protected void addCellStyle(int rowIndex, String styleClass){
        if (isRowSelect()){
            for (int cellIndex=0; cellIndex<getCellCount(); cellIndex++){
                Dojo.addClass(getCell(rowIndex, cellIndex), styleClass);
            }
        } else {
            //Dojo.addClass(getCell(rowIndex, getFocusedCell()), Dijit.getTheme().dijitFocusedName());
        }
    }
    
    protected void removeCellStyle(int rowIndex, String styleClass){
        if (isRowSelect()){
            for (int cellIndex=0; cellIndex<getCellCount(); cellIndex++){
                Dojo.removeClass(getCell(rowIndex, cellIndex), styleClass);
            }
        } else {
            //Dojo.removeClass(getCell(rowIndex, getFocusedCell()), Dijit.getTheme().dijitFocusedName());
        }
    }
    

    // Store Item/Row assignment
    
    
    public List<Element> getRowCells(int rowIndex){
        return getRender().getRowCells(rowIndex);
    }
    
    public Element getCell(int rowIndex, int cellIndex){
        return getRender().getCell(rowIndex, cellIndex);
    }
    
    public int getCellIndex(Element cellElement){
        return getRender().getCellIndex(cellElement);
    }

    @Override
    public int getCellCount() {
        return getRender().getCellCount();
    }

    @Override
    public boolean isCellSelected(int rowIndex, int cellIndex) {
        // FIXME e qndo nao for rowSelect?
        return getSelection().contains(rowIndex);
    }

    
    // Implements ModelListener
    
    
    @Override
    public void doAttach(Store<Object> parent) throws AttachException {
        if (!(parent instanceof ModeledStore<?>)){
            throw new AttachException(this, "the attached store should be a ModeledStore descendant");
        }
        super.doAttach(parent);
        getRender().setCellCount(getStore().getModel().getColumns().size());
    }

    @Override
    public void doDetach(Store<Object> parent) {
        // don't need to remove the columns, it will goes away with the rows
        super.doDetach(parent);
    }

    @Override
    public void onColumnAdded(StoreColumn<Object, ?> column) {
        getRender().addCell(column.getColumnIndex());
    }

    @Override
    public void onColumnChanged(StoreColumn<Object, ?> column) {
        // don't needs update
    }

    @Override
    public void onColumnRemoved(StoreColumn<Object, ?> column) {
        getRender().removeCell(column.getColumnIndex());
    }

    @Override
    public void onColumnReplaced(int columnIndex, StoreColumn<Object, ?> oldColumn, StoreColumn<Object, ?> newColumn) {
        onColumnRefresh(newColumn);
    }

    @Override
    public void onColumnRefresh(StoreColumn<Object, ?> column) {
        getRender().updateCells(column.getColumnIndex());
    }


    // Implements DataListener
    
    
    @Override
    public void onRefreshValue(Object item, int columnIndex) {
        getRender().updateCells(item, columnIndex);
    }
 
    
    // Event Handlers


    @Override
    protected void onRowClick(Event event, int rowIndex) {
        //int cellIndex = 0;

        //if (( cellIndex = getCellIndexForEvent(event) ) != -1) 
        {
           // onCellClick(event, rowIndex, cellIndex);
        }
        
        super.onRowClick(event, rowIndex);
    }
    
    protected void onCellClick(Event event, int rowIndex, int cellIndex) {
        // TODO ModeledView:browserEvents 
    }


    // Selection Management
    
    
    @Override
    protected void onRowFocus(int rowIndex) {
        addCellStyle(rowIndex, Dijit.getTheme().dijitFocusedName());
        super.onRowFocus(rowIndex);
    }
    
    @Override
    protected void onRowBlur(int rowIndex) {
        removeCellStyle(rowIndex, Dijit.getTheme().dijitFocusedName());
        super.onRowBlur(rowIndex);
    }

    @Override
    protected void onRowSelect(int rowIndex) {
        addCellStyle(rowIndex, Dijit.getTheme().dijitSelectedName());
        super.onRowSelect(rowIndex);
    }
    
    @Override
    protected void onRowDeselect(int rowIndex) {
        removeCellStyle(rowIndex, Dijit.getTheme().dijitSelectedName());
        super.onRowDeselect(rowIndex);
    }

}
